package solution;

import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Stack;

/**
 * @author or2
 * @date 2021/7/29 16:52
 */
public class EvalInfixExpression {

    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    public int solve (String s) {
        var stackNums = new LinkedList<Integer>();
        var stackOperate = new LinkedList<Character>();

        int sum = 0;
        for (char c : s.toCharArray()) {
//            '0':	48, '9':  57
            if (c > 47 && c < 59) {
                sum *= 10;
                sum += c - 48;
                continue;
            }

            if (sum != 0) {
                stackNums.push(sum);
                sum = 0;
            }

            operate(stackOperate, stackNums, c);
        }

        if (sum != 0) {
            stackNums.push(sum);
        }
        if (stackOperate.size() != 0) {
            int b = stackNums.pop();
            int a = stackNums.pop();
            char op = stackOperate.pop();
            switch (op) {
                case '*':
                    stackNums.push(a * b);
                    break;
                case '+':
                    stackNums.push(a + b);
                    break;
                case '-':
                    stackNums.push(a - b);
                    break;
                default:
                    throw new IllegalStateException("未期望的值: " + op);
            }
        }
        return stackNums.pop();
    }

    /**
     * 根据不同操作数进行操作
     * @param stackOperate 操作数栈
     * @param c 操作数
     */
    private void operate(LinkedList<Character> stackOperate, LinkedList<Integer> stackNums, char c) {
        switch (c) {
            case '(':
                stackOperate.push(c);
                break;
            case ')':
                while (stackOperate.peek() != '(') {
                    int b = stackNums.pop();
                    int a = stackNums.pop();
                    char op = stackOperate.pop();
                    switch (op) {
                        case '*':
                            stackNums.push(a * b);
                            break;
                        case '+':
                            stackNums.push(a + b);
                            break;
                        case '-':
                            stackNums.push(a - b);
                            break;
                        default:
                            throw new IllegalStateException("未期望的值: " + op);
                    }
                }
                stackOperate.pop();
                break;
            case '+':
            case '-':
//                使用循环确保完整
                while (stackOperate.size() != 0 && stackOperate.peek() != '(') {
                    int b = stackNums.pop();
                    int a = stackNums.pop();
                    char op = stackOperate.pop();
                    switch (op) {
                        case '*':
                            stackNums.push(a * b);
                            break;
                        case '+':
                            stackNums.push(a + b);
                            break;
                        case '-':
                            stackNums.push(a - b);
                            break;
                        default:
                            throw new IllegalStateException("未期望的值: " + op);
                    }
                }
                stackOperate.push(c);
                break;
            case '*':
                if (stackOperate.size() != 0 && stackOperate.peek() == '*') {
                    int a = stackNums.pop();
                    int b = stackNums.pop();
                    stackOperate.pop();
                    stackNums.push(a * b);
                }
                stackOperate.push(c);
                break;
            default:
                throw new NoSuchElementException("无此操作符!");
        }
    }
}
